"""
字典管理服务
提供字典数据的CRUD操作和业务逻辑
"""

import logging
import uuid
from datetime import datetime
from typing import List, Optional, Dict, Any
from sqlalchemy.orm import Session
from sqlalchemy import and_, or_

from src.app.database.models import Dictionary
from src.app.database.database import get_database_manager
from src.app.modules.dictionary.cache import DictionaryCache
from src.app.modules.dictionary.utils import DictionaryUtils

logger = logging.getLogger(__name__)

class DictionaryService:
    """字典管理服务类"""
    
    def __init__(self):
        self.db_manager = get_database_manager()
        self.cache = DictionaryCache()
        self.utils = DictionaryUtils()
    
    def create_dictionary(self, dict_data: Dict[str, Any]) -> Dict[str, Any]:
        """
        创建字典项
        
        Args:
            dict_data: 字典数据字典
            
        Returns:
            创建结果字典
        """
        try:
            with self.db_manager.get_session() as session:
                # 生成字典ID
                dict_id = dict_data.get('dict_id') or str(uuid.uuid4())
                
                # 检查是否已存在
                existing = session.query(Dictionary).filter(
                    and_(
                        Dictionary.dict_type == dict_data['dict_type'],
                        Dictionary.dict_code == dict_data['dict_code']
                    )
                ).first()
                
                if existing:
                    return {
                        'success': False,
                        'message': f"字典类型'{dict_data['dict_type']}'中已存在代码'{dict_data['dict_code']}'"
                    }
                
                # 创建字典对象
                dictionary = Dictionary(
                    dict_id=dict_id,
                    dict_type=dict_data['dict_type'],
                    dict_code=dict_data['dict_code'],
                    dict_name=dict_data['dict_name'],
                    parent_code=dict_data.get('parent_code'),
                    sort_order=dict_data.get('sort_order', 0),
                    is_system=dict_data.get('is_system', False),
                    description=dict_data.get('description', ''),
                    create_time=datetime.now(),
                    update_time=datetime.now()
                )
                
                # 保存到数据库
                session.add(dictionary)
                session.commit()
                
                # 清除缓存
                self.cache.clear_cache()
                
                logger.info(f"创建字典成功: {dict_id}")
                
                return {
                    'success': True,
                    'data': {
                        'dict_id': dict_id,
                        'dict_type': dictionary.dict_type,
                        'dict_code': dictionary.dict_code,
                        'dict_name': dictionary.dict_name
                    },
                    'message': '字典创建成功'
                }
                
        except Exception as e:
            logger.error(f"创建字典失败: {e}")
            return {
                'success': False,
                'message': f'创建字典失败: {str(e)}'
            }
    
    def update_dictionary(self, dict_id: str, dict_data: Dict[str, Any]) -> Dict[str, Any]:
        """
        更新字典项
        
        Args:
            dict_id: 字典ID
            dict_data: 更新数据字典
            
        Returns:
            更新结果字典
        """
        try:
            with self.db_manager.get_session() as session:
                # 查找字典项
                dictionary = session.query(Dictionary).filter(
                    Dictionary.dict_id == dict_id
                ).first()
                
                if not dictionary:
                    return {
                        'success': False,
                        'message': f'字典项不存在: {dict_id}'
                    }
                
                # 检查是否为系统字典
                if dictionary.is_system:
                    return {
                        'success': False,
                        'message': '系统字典不允许修改'
                    }
                
                # 检查类型和代码是否重复
                if 'dict_type' in dict_data or 'dict_code' in dict_data:
                    new_type = dict_data.get('dict_type', dictionary.dict_type)
                    new_code = dict_data.get('dict_code', dictionary.dict_code)
                    
                    existing = session.query(Dictionary).filter(
                        and_(
                            Dictionary.dict_type == new_type,
                            Dictionary.dict_code == new_code,
                            Dictionary.dict_id != dict_id
                        )
                    ).first()
                    
                    if existing:
                        return {
                            'success': False,
                            'message': f"字典类型'{new_type}'中已存在代码'{new_code}'"
                        }
                
                # 更新字段
                for key, value in dict_data.items():
                    if hasattr(dictionary, key) and key not in ['dict_id', 'create_time']:
                        setattr(dictionary, key, value)
                
                dictionary.update_time = datetime.now()
                
                # 保存到数据库
                session.commit()
                
                # 清除缓存
                self.cache.clear_cache()
                
                logger.info(f"更新字典成功: {dict_id}")
                
                return {
                    'success': True,
                    'data': {
                        'dict_id': dictionary.dict_id,
                        'dict_type': dictionary.dict_type,
                        'dict_code': dictionary.dict_code,
                        'dict_name': dictionary.dict_name
                    },
                    'message': '字典更新成功'
                }
                
        except Exception as e:
            logger.error(f"更新字典失败: {e}")
            return {
                'success': False,
                'message': f'更新字典失败: {str(e)}'
            }
    
    def delete_dictionary(self, dict_id: str) -> Dict[str, Any]:
        """
        删除字典项
        
        Args:
            dict_id: 字典ID
            
        Returns:
            删除结果字典
        """
        try:
            with self.db_manager.get_session() as session:
                # 查找字典项
                dictionary = session.query(Dictionary).filter(
                    Dictionary.dict_id == dict_id
                ).first()
                
                if not dictionary:
                    return {
                        'success': False,
                        'message': f'字典项不存在: {dict_id}'
                    }
                
                # 检查是否为系统字典
                if dictionary.is_system:
                    return {
                        'success': False,
                        'message': '系统字典不允许删除'
                    }
                
                # 检查是否有子项
                children = session.query(Dictionary).filter(
                    Dictionary.parent_code == dictionary.dict_code
                ).count()
                
                if children > 0:
                    return {
                        'success': False,
                        'message': f'存在{children}个子字典项，无法删除'
                    }
                
                # 删除字典项
                session.delete(dictionary)
                session.commit()
                
                # 清除缓存
                self.cache.clear_cache()
                
                logger.info(f"删除字典成功: {dict_id}")
                
                return {
                    'success': True,
                    'message': '字典删除成功'
                }
                
        except Exception as e:
            logger.error(f"删除字典失败: {e}")
            return {
                'success': False,
                'message': f'删除字典失败: {str(e)}'
            }
    
    def get_dictionary_by_id(self, dict_id: str) -> Optional[Dict[str, Any]]:
        """
        根据ID获取字典项
        
        Args:
            dict_id: 字典ID
            
        Returns:
            字典数据字典或None
        """
        try:
            # 先从缓存获取
            cached = self.cache.get_dictionary(dict_id)
            if cached:
                return cached
            
            # 从数据库获取
            with self.db_manager.get_session() as session:
                dictionary = session.query(Dictionary).filter(
                    Dictionary.dict_id == dict_id
                ).first()
                
                if dictionary:
                    result = self.utils.dictionary_to_dict(dictionary)
                    # 缓存结果
                    self.cache.set_dictionary(dict_id, result)
                    return result
                
                return None
                
        except Exception as e:
            logger.error(f"获取字典失败: {e}")
            return None
    
    def get_dictionaries_by_type(self, dict_type: str, include_system: bool = True) -> List[Dict[str, Any]]:
        """
        根据类型获取字典列表
        
        Args:
            dict_type: 字典类型
            include_system: 是否包含系统字典
            
        Returns:
            字典列表
        """
        try:
            # 先从缓存获取
            cache_key = f"type_{dict_type}_{include_system}"
            cached = self.cache.get_dictionary_list(cache_key)
            if cached:
                return cached
            
            # 从数据库获取
            with self.db_manager.get_session() as session:
                query = session.query(Dictionary).filter(
                    Dictionary.dict_type == dict_type
                )
                
                if not include_system:
                    query = query.filter(Dictionary.is_system == False)
                
                dictionaries = query.order_by(
                    Dictionary.sort_order,
                    Dictionary.dict_code
                ).all()
                
                result = [self.utils.dictionary_to_dict(d) for d in dictionaries]
                
                # 缓存结果
                self.cache.set_dictionary_list(cache_key, result)
                
                return result
                
        except Exception as e:
            logger.error(f"获取字典列表失败: {e}")
            return []
    
    def get_all_types(self) -> List[str]:
        """
        获取所有字典类型
        
        Returns:
            字典类型列表
        """
        try:
            # 先从缓存获取
            cached = self.cache.get_dictionary_list("all_types")
            if cached:
                return cached
            
            # 从数据库获取
            with self.db_manager.get_session() as session:
                types = session.query(Dictionary.dict_type).distinct().all()
                result = [t[0] for t in types]
                
                # 缓存结果
                self.cache.set_dictionary_list("all_types", result)
                
                return result
                
        except Exception as e:
            logger.error(f"获取字典类型失败: {e}")
            return []
    
    def search_dictionaries(self, keyword: str, dict_type: str = None) -> List[Dict[str, Any]]:
        """
        搜索字典项
        
        Args:
            keyword: 搜索关键词
            dict_type: 字典类型（可选）
            
        Returns:
            搜索结果列表
        """
        try:
            with self.db_manager.get_session() as session:
                query = session.query(Dictionary)
                
                # 构建搜索条件
                conditions = [
                    or_(
                        Dictionary.dict_name.contains(keyword),
                        Dictionary.dict_code.contains(keyword),
                        Dictionary.description.contains(keyword)
                    )
                ]
                
                if dict_type:
                    conditions.append(Dictionary.dict_type == dict_type)
                
                dictionaries = query.filter(and_(*conditions)).order_by(
                    Dictionary.dict_type,
                    Dictionary.sort_order,
                    Dictionary.dict_code
                ).all()
                
                return [self.utils.dictionary_to_dict(d) for d in dictionaries]
                
        except Exception as e:
            logger.error(f"搜索字典失败: {e}")
            return []
    
    def get_tree_structure(self, dict_type: str) -> List[Dict[str, Any]]:
        """
        获取字典树形结构
        
        Args:
            dict_type: 字典类型
            
        Returns:
            树形结构列表
        """
        try:
            dictionaries = self.get_dictionaries_by_type(dict_type)
            return self.utils.build_tree_structure(dictionaries)
            
        except Exception as e:
            logger.error(f"获取树形结构失败: {e}")
            return []
    
    def get_all_dictionaries(self, filters: Dict[str, Any] = None) -> List[Dict[str, Any]]:
        """
        获取所有字典项（支持筛选）
        
        Args:
            filters: 筛选条件
            
        Returns:
            字典列表
        """
        try:
            if not filters:
                filters = {}
            
            # 获取所有字典类型
            dict_types = self.get_all_types()
            
            # 获取所有字典数据
            all_dictionaries = []
            for dict_type in dict_types:
                dictionaries = self.get_dictionaries_by_type(dict_type)
                all_dictionaries.extend(dictionaries)
            
            # 应用筛选条件
            if filters.get('dict_type'):
                all_dictionaries = [d for d in all_dictionaries if d['dict_type'] == filters['dict_type']]
            
            if filters.get('dict_name'):
                keyword = filters['dict_name'].lower()
                all_dictionaries = [d for d in all_dictionaries 
                                  if keyword in d['dict_name'].lower() or keyword in d['dict_code'].lower()]
            
            return all_dictionaries
            
        except Exception as e:
            logger.error(f"获取所有字典失败: {e}")
            return []
    
    def get_statistics(self) -> Dict[str, Any]:
        """
        获取字典统计信息
        
        Returns:
            统计信息字典
        """
        return self.utils.get_statistics()
    
    def validate_dictionary_data(self, dict_data: Dict[str, Any], is_update: bool = False) -> Dict[str, Any]:
        """
        验证字典数据
        
        Args:
            dict_data: 字典数据
            is_update: 是否为更新操作
            
        Returns:
            验证结果
        """
        errors = []
        
        # 必填字段验证
        required_fields = ['dict_type', 'dict_code', 'dict_name']
        if not is_update:
            for field in required_fields:
                if not dict_data.get(field):
                    errors.append(f'字段{field}不能为空')
        else:
            for field in required_fields:
                if field in dict_data and not dict_data[field]:
                    errors.append(f'字段{field}不能为空')
        
        # 字段长度验证
        if dict_data.get('dict_type') and len(dict_data['dict_type']) > 50:
            errors.append('字典类型长度不能超过50个字符')
        
        if dict_data.get('dict_code') and len(dict_data['dict_code']) > 50:
            errors.append('字典代码长度不能超过50个字符')
        
        if dict_data.get('dict_name') and len(dict_data['dict_name']) > 100:
            errors.append('字典名称长度不能超过100个字符')
        
        # 排序号验证
        if dict_data.get('sort_order') is not None:
            try:
                sort_order = int(dict_data['sort_order'])
                if sort_order < 0:
                    errors.append('排序号不能小于0')
            except ValueError:
                errors.append('排序号必须为整数')
        
        return {
            'valid': len(errors) == 0,
            'errors': errors
        }
    
    def update_dictionary_by_code(self, dict_type: str, dict_code: str, dict_data: Dict[str, Any]) -> Dict[str, Any]:
        """
        根据类型和代码更新字典项
        
        Args:
            dict_type: 字典类型
            dict_code: 字典代码
            dict_data: 更新数据字典
            
        Returns:
            更新结果字典
        """
        try:
            with self.db_manager.get_session() as session:
                # 查找字典项
                dictionary = session.query(Dictionary).filter(
                    and_(
                        Dictionary.dict_type == dict_type,
                        Dictionary.dict_code == dict_code
                    )
                ).first()
                
                if not dictionary:
                    return {
                        'success': False,
                        'message': f'字典项不存在: {dict_type}.{dict_code}'
                    }
                
                # 检查是否为系统字典
                if dictionary.is_system:
                    return {
                        'success': False,
                        'message': '系统字典不允许修改'
                    }
                
                # 更新字段
                for key, value in dict_data.items():
                    if hasattr(dictionary, key) and key not in ['dict_id', 'dict_type', 'dict_code', 'create_time']:
                        setattr(dictionary, key, value)
                
                dictionary.update_time = datetime.now()
                
                # 保存到数据库
                session.commit()
                
                # 清除缓存
                self.cache.clear_cache()
                
                logger.info(f"更新字典成功: {dict_type}.{dict_code}")
                
                return {
                    'success': True,
                    'data': {
                        'dict_id': dictionary.dict_id,
                        'dict_type': dictionary.dict_type,
                        'dict_code': dictionary.dict_code,
                        'dict_name': dictionary.dict_name
                    },
                    'message': '字典更新成功'
                }
                
        except Exception as e:
            logger.error(f"更新字典失败: {e}")
            return {
                'success': False,
                'message': f'更新字典失败: {str(e)}'
            }